/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 *
 */

import crypto from 'crypto';

import { ContinualEvent } from './event/continual-event.js';
import { CounterEvent } from './event/counter-event.js';
import { DurationEvent } from './event/duration-event.js';
import { GaugeEvent } from './event/gauge-event.js';
import { InstantEvent } from './event/instant-event.js';
import { LogEvent, MetricLogType } from './event/log-event.js';
import { MarkEvent } from './event/mark-event.js';
import { MetadataEvent, MetadataEventState } from './event/metadata-event.js';
import { ObjectEvent, ObjectEventState } from './event/object-event.js';
import { MetricService } from './metric-service.js';

export const MAIN_THREAD = 'Main Thread';

/**
 * 矩阵工厂
 *
 * @since 2022/8/17
 */
export class MetricFactory {
  static getUuid() {
    return crypto.randomUUID();
  }

  static createDurationEvent(name: string, description: string, group: string, tid?: string): DurationEvent {
    const durationEvent = new DurationEvent(MetricFactory.getUuid(), name, description, process.pid, group, tid ?? MAIN_THREAD);
    MetricService.getInstance().submit(durationEvent);
    return durationEvent;
  }

  static createInstantEvent(name: string, description: string, tid?: string): InstantEvent {
    const instantEvent = new InstantEvent(MetricFactory.getUuid(), name, description, process.pid, tid ?? MAIN_THREAD);
    MetricService.getInstance().submit(instantEvent);
    return instantEvent;
  }

  static createCounterEvent(name: string, description: string, success?: number, failed?: number, tid?: string): CounterEvent {
    const counterEvent = new CounterEvent(MetricFactory.getUuid(), name, description, process.pid, tid ?? MAIN_THREAD, success, failed);
    MetricService.getInstance().submit(counterEvent);
    return counterEvent;
  }

  static createGaugeEvent(name: string, utilization: number, description: string, tid?: string): GaugeEvent {
    const gaugeEvent = new GaugeEvent(MetricFactory.getUuid(), name, description, process.pid, tid ?? MAIN_THREAD, utilization);
    MetricService.getInstance().submit(gaugeEvent);
    return gaugeEvent;
  }

  static createObjectEvent(name: string, objectId: string, state: ObjectEventState, description: string, snapshot?: object, tid?: string): ObjectEvent {
    const objectEvent = new ObjectEvent(MetricFactory.getUuid(), name, description, process.pid, tid ?? MAIN_THREAD, objectId, state, snapshot);
    MetricService.getInstance().submit(objectEvent);
    return objectEvent;
  }

  static createMetadataEvent(name: string, state: MetadataEventState, description: string, tid?: string): MetadataEvent {
    const metadataEvent = new MetadataEvent(MetricFactory.getUuid(), name, description, process.pid, tid ?? MAIN_THREAD, state);
    MetricService.getInstance().submit(metadataEvent);
    return metadataEvent;
  }

  static createMarkEvent(name: string, description: string, tid?: string): MarkEvent {
    const markEvent = new MarkEvent(MetricFactory.getUuid(), name, description, process.pid, tid ?? MAIN_THREAD);
    MetricService.getInstance().submit(markEvent);
    return markEvent;
  }

  static createLogEvent(name: string, type: MetricLogType, tid?: string, description?: string): LogEvent {
    const logEvent = new LogEvent(MetricFactory.getUuid(), name, description ?? '', process.pid, tid ?? MAIN_THREAD, type);
    MetricService.getInstance().submit(logEvent);
    return logEvent;
  }

  static createContinualEvent(name: string, description: string, totalTime?: number, frequency?: number, tid?: string): ContinualEvent {
    const continualEvent = new ContinualEvent(MetricFactory.getUuid(), name, description, process.pid, tid ?? MAIN_THREAD, totalTime, frequency);
    MetricService.getInstance().submit(continualEvent);
    return continualEvent;
  }
}
